From 813b214e011bcf3ca6eda99b228044fb3eec341a Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 26 Jun 2004 16:41:33 +0000 Subject: [PATCH] bitkeeper revision 1.1018 (40dda73dmOqfB0T5ld-VOSobhH5ljg) cleanups --- tools/xc/lib/xc.h | 20 +- tools/xc/lib/xc_domain.c | 21 +- tools/xc/lib/xc_linux_save.c | 876 +++++++++++++++++------------------ tools/xc/py/Xc.c | 2 +- 4 files changed, 454 insertions(+), 465 deletions(-) diff --git a/tools/xc/lib/xc.h b/tools/xc/lib/xc.h index 239495a5a9..ca092975ce 100644 --- a/tools/xc/lib/xc.h +++ b/tools/xc/lib/xc.h @@ -47,7 +47,7 @@ typedef struct xc_shadow_control_stats_st int xc_domain_create(int xc_handle, unsigned int mem_kb, const char *name, - int cpu, + int cpu, u32 *pdomid); int xc_domain_pause(int xc_handle, u32 domid); @@ -66,9 +66,9 @@ int xc_domain_getinfo(int xc_handle, int xc_shadow_control(int xc_handle, u32 domid, unsigned int sop, - unsigned long *dirty_bitmap, - unsigned long pages, - xc_shadow_control_stats_t *stats); + unsigned long *dirty_bitmap, + unsigned long pages, + xc_shadow_control_stats_t *stats); #define XCFLAGS_VERBOSE 1 @@ -78,14 +78,14 @@ int xc_shadow_control(int xc_handle, int xc_linux_save(int xc_handle, u32 domid, unsigned int flags, - int (*writerfn)(void *, const void *, size_t), - void *writerst ); + int (*writerfn)(void *, const void *, size_t), + void *writerst); int xc_linux_restore(int xc_handle, u32 domid, - unsigned int flags, - int (*readerfn)(void *, void *, size_t), - void *readerst, + unsigned int flags, + int (*readerfn)(void *, void *, size_t), + void *readerst, u32 *pdomid); int xc_linux_build(int xc_handle, @@ -94,7 +94,7 @@ int xc_linux_build(int xc_handle, const char *ramdisk_name, const char *cmdline, unsigned int control_evtchn, - unsigned long flags); + unsigned long flags); int xc_netbsd_build(int xc_handle, u32 domid, diff --git a/tools/xc/lib/xc_domain.c b/tools/xc/lib/xc_domain.c index 38b3e2ee34..ab83d0ce7b 100644 --- a/tools/xc/lib/xc_domain.c +++ b/tools/xc/lib/xc_domain.c @@ -118,9 +118,9 @@ int xc_domain_getinfo(int xc_handle, } int xc_domain_getfullinfo(int xc_handle, - u32 domid, - dom0_op_t *op, - full_execution_context_t *ctxt ) + u32 domid, + dom0_op_t *op, + full_execution_context_t *ctxt ) { int rc; op->cmd = DOM0_GETDOMAININFO; @@ -129,18 +129,18 @@ int xc_domain_getfullinfo(int xc_handle, rc = do_dom0_op(xc_handle, op); if ( ((u32)op->u.getdomaininfo.domain != domid) && rc > 0 ) - return -ESRCH; + return -ESRCH; else - return rc; + return rc; } int xc_shadow_control(int xc_handle, u32 domid, unsigned int sop, - unsigned long *dirty_bitmap, - unsigned long pages, - xc_shadow_control_stats_t *stats ) + unsigned long *dirty_bitmap, + unsigned long pages, + xc_shadow_control_stats_t *stats ) { int rc; dom0_op_t op; @@ -152,8 +152,9 @@ int xc_shadow_control(int xc_handle, rc = do_dom0_op(xc_handle, &op); - if(stats) memcpy(stats, &op.u.shadow_control.stats, - sizeof(xc_shadow_control_stats_t)); + if ( stats ) + memcpy(stats, &op.u.shadow_control.stats, + sizeof(xc_shadow_control_stats_t)); return (rc == 0) ? op.u.shadow_control.pages : rc; } diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index e93120a08b..b84521cd6b 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -26,8 +26,6 @@ #define DDPRINTF(_f, _a...) ((void)0) #endif - - /* This may allow us to create a 'quiet' command-line option, if necessary. */ #define verbose_printf(_f, _a...) \ do { \ @@ -41,67 +39,61 @@ * in the guest's pseudophysical map. * 0x80000000-3 mark the shared_info, and blk/net rings */ -#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \ - (((_mfn) < (1024*1024)) && \ - ( ( (live_mfn_to_pfn_table[_mfn] < nr_pfns) && \ - (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn)) ) || \ -\ - (live_mfn_to_pfn_table[_mfn] >= 0x80000000 && \ - live_mfn_to_pfn_table[_mfn] <= 0x80000003 ) || \ - live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == 0x80000004 ) ) +#define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \ + (((_mfn) < (1024*1024)) && \ + (((live_mfn_to_pfn_table[_mfn] < nr_pfns) && \ + (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn))) || \ + ((live_mfn_to_pfn_table[_mfn] >= 0x80000000) && \ + (live_mfn_to_pfn_table[_mfn] <= 0x80000003)) || \ + (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == 0x80000004))) /* Returns TRUE if MFN is successfully converted to a PFN. */ -#define translate_mfn_to_pfn(_pmfn) \ -({ \ - unsigned long mfn = *(_pmfn); \ - int _res = 1; \ - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \ - _res = 0; \ - else \ - *(_pmfn) = live_mfn_to_pfn_table[mfn]; \ - _res; \ +#define translate_mfn_to_pfn(_pmfn) \ +({ \ + unsigned long mfn = *(_pmfn); \ + int _res = 1; \ + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) \ + _res = 0; \ + else \ + *(_pmfn) = live_mfn_to_pfn_table[mfn]; \ + _res; \ }) - -/* test_bit */ static inline int test_bit ( int nr, volatile void * addr) { - return ( ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] >> - (nr % (sizeof(unsigned long)*8) ) ) & 1; + return (((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] >> + (nr % (sizeof(unsigned long)*8))) & 1; } static inline void clear_bit ( int nr, volatile void * addr) { ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] &= - ~(1 << (nr % (sizeof(unsigned long)*8) ) ); + ~(1 << (nr % (sizeof(unsigned long)*8) ) ); } static inline void set_bit ( int nr, volatile void * addr) { ((unsigned long*)addr)[nr/(sizeof(unsigned long)*8)] |= - (1 << (nr % (sizeof(unsigned long)*8) ) ); + (1 << (nr % (sizeof(unsigned long)*8) ) ); } -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ +/* Returns the hamming weight (i.e. the number of bits set) in a N-bit word */ static inline unsigned int hweight32(unsigned int w) { - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); } static inline int count_bits ( int nr, volatile void *addr) { int i, count = 0; unsigned long *p = (unsigned long *)addr; - // we know the array is padded to unsigned long + /* We know that the array is padded to unsigned long. */ for(i=0;i>(order_nr-10)) | ( i<<10 ) ) & - ((1<= nr ); // this won't ever loop if nr is a power of 2 + do { i = ((i>>(order_nr-10)) | ( i<<10 ) ) & ((1<= nr ); /* this won't ever loop if nr is a power of 2 */ return i; } @@ -154,12 +142,12 @@ static long long llgettimeofday() static long long tv_delta( struct timeval *new, struct timeval *old ) { return ((new->tv_sec - old->tv_sec)*1000000 ) + - (new->tv_usec - old->tv_usec); + (new->tv_usec - old->tv_usec); } static int print_stats( int xc_handle, u32 domid, - int pages_sent, xc_shadow_control_stats_t *stats, - int print ) + int pages_sent, xc_shadow_control_stats_t *stats, + int print ) { static struct timeval wall_last; static long long d0_cpu_last; @@ -175,10 +163,8 @@ static int print_stats( int xc_handle, u32 domid, d0_cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000; d1_cpu_now = xc_domain_get_cpu_usage( xc_handle, domid )/1000; - if ( d0_cpu_now == -1 || d1_cpu_now == -1 ) - { - printf("ARRHHH!!\n"); - } + if ( (d0_cpu_now == -1) || (d1_cpu_now == -1) ) + printf("ARRHHH!!\n"); wall_delta = tv_delta(&wall_now,&wall_last)/1000; @@ -187,66 +173,63 @@ static int print_stats( int xc_handle, u32 domid, d0_cpu_delta = (d0_cpu_now - d0_cpu_last)/1000; d1_cpu_delta = (d1_cpu_now - d1_cpu_last)/1000; - if(print) - printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, dirtied %dMb/s\n", - wall_delta, - (int)((d0_cpu_delta*100)/wall_delta), - (int)((d1_cpu_delta*100)/wall_delta), - (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)), - (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000)) - ); + if ( print ) + printf("delta %lldms, dom0 %d%%, target %d%%, sent %dMb/s, " + "dirtied %dMb/s\n", + wall_delta, + (int)((d0_cpu_delta*100)/wall_delta), + (int)((d1_cpu_delta*100)/wall_delta), + (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)), + (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000))); d0_cpu_last = d0_cpu_now; d1_cpu_last = d1_cpu_now; - wall_last = wall_now; + wall_last = wall_now; return 0; } static int analysis_phase( int xc_handle, u32 domid, - int nr_pfns, unsigned long *arr ) + int nr_pfns, unsigned long *arr ) { long long start, now; xc_shadow_control_stats_t stats; start = llgettimeofday(); - while(0) + while ( 0 ) { - int i; - - xc_shadow_control( xc_handle, domid, - DOM0_SHADOW_CONTROL_OP_CLEAN2, - arr, nr_pfns, NULL); - printf("#Flush\n"); - for(i=0;i<100;i++) - { - usleep(10000); - now = llgettimeofday(); - xc_shadow_control( xc_handle, domid, - DOM0_SHADOW_CONTROL_OP_PEEK, - NULL, 0, &stats); - - printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld dirty_block= %ld\n", - ((now-start)+500)/1000, - stats.fault_count, stats.dirty_count, - stats.dirty_net_count, stats.dirty_block_count ); - - } - - + int i; + + xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_CLEAN2, + arr, nr_pfns, NULL); + printf("#Flush\n"); + for ( i = 0; i < 100; i++ ) + { + usleep(10000); + now = llgettimeofday(); + xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_PEEK, + NULL, 0, &stats); + + printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld " + "dirty_block= %ld\n", + ((now-start)+500)/1000, + stats.fault_count, stats.dirty_count, + stats.dirty_net_count, stats.dirty_block_count); + } } - return -1; } int xc_linux_save(int xc_handle, u32 domid, - unsigned int flags, - int (*writerfn)(void *, const void *, size_t), - void *writerst ) + unsigned int flags, + int (*writerfn)(void *, const void *, size_t), + void *writerst ) { dom0_op_t op; int rc = 1, i, j, k, last_iter, iter = 0; @@ -257,8 +240,8 @@ int xc_linux_save(int xc_handle, int sent_last_iter, sent_this_iter, skip_this_iter; /* Important tuning parameters */ - int max_iters = 29; // limit us to 30 times round loop - int max_factor = 3; // never send more than 3x nr_pfns + int max_iters = 29; /* limit us to 30 times round loop */ + int max_factor = 3; /* never send more than 3x nr_pfns */ /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; @@ -321,14 +304,14 @@ int xc_linux_save(int xc_handle, if ( xc_domain_pause( xc_handle, domid ) ) { - PERROR("Could not pause domain"); - goto out; + PERROR("Could not pause domain"); + goto out; } if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) ) { - PERROR("Could not get full domain info"); - goto out; + PERROR("Could not get full domain info"); + goto out; } memcpy(name, op.u.getdomaininfo.name, sizeof(name)); shared_info_frame = op.u.getdomaininfo.shared_info_frame; @@ -343,8 +326,8 @@ int xc_linux_save(int xc_handle, /* Map the suspend-record MFN to pin it. The page must be owned by domid for this to succeed. */ p_srec = mfn_mapper_map_single(xc_handle, domid, - sizeof(*p_srec), PROT_READ, - ctxt.cpu_ctxt.esi ); + sizeof(*p_srec), PROT_READ, + ctxt.cpu_ctxt.esi ); if (!p_srec) { @@ -363,9 +346,9 @@ int xc_linux_save(int xc_handle, /* the pfn_to_mfn_frame_list fits in a single page */ live_pfn_to_mfn_frame_list = - mfn_mapper_map_single(xc_handle, domid, - PAGE_SIZE, PROT_READ, - p_srec->pfn_to_mfn_frame_list ); + mfn_mapper_map_single(xc_handle, domid, + PAGE_SIZE, PROT_READ, + p_srec->pfn_to_mfn_frame_list ); if (!live_pfn_to_mfn_frame_list) { @@ -375,20 +358,20 @@ int xc_linux_save(int xc_handle, /* Track the mfn_to_pfn table down from the domains PT */ { - unsigned long *pgd; - unsigned long mfn_to_pfn_table_start_mfn; + unsigned long *pgd; + unsigned long mfn_to_pfn_table_start_mfn; - pgd = mfn_mapper_map_single(xc_handle, domid, - PAGE_SIZE, PROT_READ, - ctxt.pt_base>>PAGE_SHIFT); + pgd = mfn_mapper_map_single(xc_handle, domid, + PAGE_SIZE, PROT_READ, + ctxt.pt_base>>PAGE_SHIFT); - mfn_to_pfn_table_start_mfn = - pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT; + mfn_to_pfn_table_start_mfn = + pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT; - live_mfn_to_pfn_table = - mfn_mapper_map_single(xc_handle, ~0UL, - PAGE_SIZE*1024, PROT_READ, - mfn_to_pfn_table_start_mfn ); + live_mfn_to_pfn_table = + mfn_mapper_map_single(xc_handle, ~0UL, + PAGE_SIZE*1024, PROT_READ, + mfn_to_pfn_table_start_mfn ); } /* Map all the frames of the pfn->mfn table. For migrate to succeed, @@ -397,9 +380,9 @@ int xc_linux_save(int xc_handle, from a safety POV anyhow. */ live_pfn_to_mfn_table = mfn_mapper_map_batch( xc_handle, domid, - PROT_READ, - live_pfn_to_mfn_frame_list, - (nr_pfns+1023)/1024 ); + PROT_READ, + live_pfn_to_mfn_frame_list, + (nr_pfns+1023)/1024 ); if( !live_pfn_to_mfn_table ) { PERROR("Couldn't map pfn_to_mfn table"); @@ -423,59 +406,59 @@ int xc_linux_save(int xc_handle, if( live ) { - if ( xc_shadow_control( xc_handle, domid, - DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY, - NULL, 0, NULL ) < 0 ) - { - ERROR("Couldn't enable shadow mode"); - goto out; - } - - if ( xc_domain_unpause( xc_handle, domid ) < 0 ) - { - ERROR("Couldn't unpause domain"); - goto out; - } - - last_iter = 0; - sent_last_iter = 1<<20; // 4GB's worth of pages + if ( xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY, + NULL, 0, NULL ) < 0 ) + { + ERROR("Couldn't enable shadow mode"); + goto out; + } + + if ( xc_domain_unpause( xc_handle, domid ) < 0 ) + { + ERROR("Couldn't unpause domain"); + goto out; + } + + last_iter = 0; + sent_last_iter = 1<<20; /* 4GB of pages */ } else - last_iter = 1; + last_iter = 1; /* calculate the power of 2 order of nr_pfns, e.g. - 15->4 16->4 17->5 */ + 15->4 16->4 17->5 */ for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ ); /* Setup to_send bitmap */ { - int sz = (nr_pfns/8) + 8; // includes slop at end of array - - to_send = malloc( sz ); - to_fix = calloc( 1, sz ); - to_skip = malloc( sz ); - - if (!to_send || !to_fix || !to_skip) - { - ERROR("Couldn't allocate to_send array"); - goto out; - } - - memset( to_send, 0xff, sz ); - - if ( mlock( to_send, sz ) ) - { - PERROR("Unable to mlock to_send"); - return 1; - } - - /* (to fix is local only) */ - - if ( mlock( to_skip, sz ) ) - { - PERROR("Unable to mlock to_skip"); - return 1; - } + int sz = (nr_pfns/8) + 8; /* includes slop at end of array */ + + to_send = malloc( sz ); + to_fix = calloc( 1, sz ); + to_skip = malloc( sz ); + + if (!to_send || !to_fix || !to_skip) + { + ERROR("Couldn't allocate to_send array"); + goto out; + } + + memset( to_send, 0xff, sz ); + + if ( mlock( to_send, sz ) ) + { + PERROR("Unable to mlock to_send"); + return 1; + } + + /* (to fix is local only) */ + + if ( mlock( to_skip, sz ) ) + { + PERROR("Unable to mlock to_skip"); + return 1; + } } @@ -493,8 +476,8 @@ int xc_linux_save(int xc_handle, if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ) { - ERROR("Unable to mlock"); - goto out; + ERROR("Unable to mlock"); + goto out; } @@ -506,16 +489,16 @@ int xc_linux_save(int xc_handle, { mfn = live_pfn_to_mfn_table[i]; - if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) ) - printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n", - i,mfn,live_mfn_to_pfn_table[mfn]); + if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) ) + printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n", + i,mfn,live_mfn_to_pfn_table[mfn]); } #endif /* Map the shared info frame */ live_shinfo = mfn_mapper_map_single(xc_handle, domid, - PAGE_SIZE, PROT_READ, - shared_info_frame); + PAGE_SIZE, PROT_READ, + shared_info_frame); if (!live_shinfo) { @@ -540,293 +523,297 @@ int xc_linux_save(int xc_handle, while(1) { - unsigned int prev_pc, sent_this_iter, N, batch; - - iter++; - sent_this_iter = 0; - skip_this_iter = 0; - prev_pc = 0; - N=0; - - verbose_printf("Saving memory pages: iter %d 0%%", iter); - - while( N < nr_pfns ) - { - unsigned int this_pc = (N * 100) / nr_pfns; - - if ( (this_pc - prev_pc) >= 5 ) - { - verbose_printf("\b\b\b\b%3d%%", this_pc); - prev_pc = this_pc; - } - - /* slightly wasteful to peek the whole array evey time, - but this is fast enough for the moment. */ - - if ( !last_iter && - xc_shadow_control(xc_handle, domid, - DOM0_SHADOW_CONTROL_OP_PEEK, - to_skip, nr_pfns, NULL) != nr_pfns ) - { - ERROR("Error peeking shadow bitmap"); - goto out; - } - - - /* load pfn_type[] with the mfn of all the pages we're doing in - this batch. */ - - for( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ ) - { - int n = permute(N, nr_pfns, order_nr ); - - if(0 && debug) - fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d [mfn]= %08lx\n", - iter, n, live_pfn_to_mfn_table[n], - test_bit(n,to_send), - live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&0xFFFFF]); - - if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip)) - skip_this_iter++; // stats keeping - - if (! ( (test_bit(n, to_send) && !test_bit(n, to_skip)) || - (test_bit(n, to_send) && last_iter) || - (test_bit(n, to_fix) && last_iter) ) ) - continue; - - /* we get here if: - 1. page is marked to_send & hasn't already been re-dirtied - 2. (ignore to_skip in last iteration) - 3. add in pages that still need fixup (net bufs) - */ - - pfn_batch[batch] = n; - pfn_type[batch] = live_pfn_to_mfn_table[n]; - - if( pfn_type[batch] == 0x80000004 ) - { - /* not currently in pusedo-physical map -- set bit - in to_fix that we must send this page in last_iter - unless its sent sooner anyhow */ - - set_bit( n, to_fix ); - if( iter>1 ) - DDPRINTF("Urk! netbuf race: iter %d, pfn %lx. mfn %lx\n", - iter,n,pfn_type[batch]); - continue; - } - - if ( last_iter && test_bit(n, to_fix ) && !test_bit(n, to_send )) - { - needed_to_fix++; - DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n", - iter,n,pfn_type[batch]); - } - - clear_bit( n, to_fix ); - - batch++; - } - - DDPRINTF("batch %d:%d (n=%d)\n",iter,batch,n); - - if(batch == 0) goto skip; // vanishingly unlikely... - - if ( (region_base = mfn_mapper_map_batch( xc_handle, domid, - PROT_READ, - pfn_type, - batch )) == 0) - { - PERROR("map batch failed"); - goto out; - } - - if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ) - { - ERROR("get_pfn_type_batch failed"); - goto out; - } - - for( j = 0; j < batch; j++ ) - { - if( (pfn_type[j] & LTAB_MASK) == XTAB) - { - DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]); - continue; - } - - if(0 && debug) - fprintf(stderr,"%d pfn= %08lx mfn= %08lx [mfn]= %08lx sum= %08lx\n", - iter, - (pfn_type[j] & LTAB_MASK) | pfn_batch[j], - pfn_type[j], - live_mfn_to_pfn_table[pfn_type[j]&(~LTAB_MASK)], - csum_page(region_base + (PAGE_SIZE*j)) - ); - - /* canonicalise mfn->pfn */ - pfn_type[j] = (pfn_type[j] & LTAB_MASK) | - pfn_batch[j]; - //live_mfn_to_pfn_table[pfn_type[j]&~LTAB_MASK]; - - } - - - if ( (*writerfn)(writerst, &batch, sizeof(int) ) ) - { - ERROR("Error when writing to state file (2)"); - goto out; - } - - if ( (*writerfn)(writerst, pfn_type, sizeof(unsigned long)*j ) ) - { - ERROR("Error when writing to state file (3)"); - goto out; - } - - /* entering this loop, pfn_type is now in pfns (Not mfns) */ - for( j = 0; j < batch; j++ ) - { - /* write out pages in batch */ - - if( (pfn_type[j] & LTAB_MASK) == XTAB) - { - DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]); - continue; - } - - if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || - ((pfn_type[j] & LTAB_MASK) == L2TAB) ) - { - - memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); - - for ( k = 0; - k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? - (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); - k++ ) - { - unsigned long pfn; - - if ( !(page[k] & _PAGE_PRESENT) ) continue; - mfn = page[k] >> PAGE_SHIFT; - pfn = live_mfn_to_pfn_table[mfn]; - - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) - { - // I don't think this should ever happen - - printf("FNI %d : [%08lx,%d] pte=%08lx, mfn=%08lx, pfn=%08lx [mfn]=%08lx\n", - j, pfn_type[j], k, - page[k], mfn, live_mfn_to_pfn_table[mfn], - (live_mfn_to_pfn_table[mfn]>28, - j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT); -#endif - - } /* end of page table rewrite for loop */ - - if ( (*writerfn)(writerst, page, PAGE_SIZE) ) - { - ERROR("Error when writing to state file (4)"); - goto out; - } - - } /* end of it's a PT page */ - else - { /* normal page */ - - if ( (*writerfn)(writerst, region_base + (PAGE_SIZE*j), PAGE_SIZE) ) - { - ERROR("Error when writing to state file (5)"); - goto out; - } - } - } /* end of the write out for this batch */ - - sent_this_iter += batch; - - } /* end of this while loop for this iteration */ - - munmap(region_base, batch*PAGE_SIZE); + unsigned int prev_pc, sent_this_iter, N, batch; - skip: + iter++; + sent_this_iter = 0; + skip_this_iter = 0; + prev_pc = 0; + N=0; - total_sent += sent_this_iter; + verbose_printf("Saving memory pages: iter %d 0%%", iter); - verbose_printf("\r %d: sent %d, skipped %d, ", - iter, sent_this_iter, skip_this_iter ); + while( N < nr_pfns ) + { + unsigned int this_pc = (N * 100) / nr_pfns; + + if ( (this_pc - prev_pc) >= 5 ) + { + verbose_printf("\b\b\b\b%3d%%", this_pc); + prev_pc = this_pc; + } + + /* slightly wasteful to peek the whole array evey time, + but this is fast enough for the moment. */ + + if ( !last_iter && + xc_shadow_control(xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_PEEK, + to_skip, nr_pfns, NULL) != nr_pfns ) + { + ERROR("Error peeking shadow bitmap"); + goto out; + } + - if ( last_iter ) - { - print_stats( xc_handle, domid, sent_this_iter, &stats, 1); + /* load pfn_type[] with the mfn of all the pages we're doing in + this batch. */ + + for ( batch = 0; batch < BATCH_SIZE && N < nr_pfns ; N++ ) + { + int n = permute(N, nr_pfns, order_nr ); + + if ( 0 && debug ) + fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d " + " [mfn]= %08lx\n", + iter, n, live_pfn_to_mfn_table[n], + test_bit(n,to_send), + live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]& + 0xFFFFF]); + + if ( !last_iter && + test_bit(n, to_send) && + test_bit(n, to_skip) ) + skip_this_iter++; /* stats keeping */ + + if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) || + (test_bit(n, to_send) && last_iter) || + (test_bit(n, to_fix) && last_iter)) ) + continue; + + /* we get here if: + 1. page is marked to_send & hasn't already been re-dirtied + 2. (ignore to_skip in last iteration) + 3. add in pages that still need fixup (net bufs) + */ + + pfn_batch[batch] = n; + pfn_type[batch] = live_pfn_to_mfn_table[n]; + + if( pfn_type[batch] == 0x80000004 ) + { + /* not currently in pusedo-physical map -- set bit + in to_fix that we must send this page in last_iter + unless its sent sooner anyhow */ + + set_bit( n, to_fix ); + if( iter>1 ) + DDPRINTF("netbuf race: iter %d, pfn %lx. mfn %lx\n", + iter,n,pfn_type[batch]); + continue; + } + + if ( last_iter && + test_bit(n, to_fix) && + !test_bit(n, to_send) ) + { + needed_to_fix++; + DPRINTF("Fix! iter %d, pfn %lx. mfn %lx\n", + iter,n,pfn_type[batch]); + } + + clear_bit(n, to_fix); + + batch++; + } + + DDPRINTF("batch %d:%d (n=%d)\n", iter, batch, n); + + if ( batch == 0 ) + goto skip; /* vanishingly unlikely... */ + + if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, + PROT_READ, + pfn_type, + batch)) == 0 ) + { + PERROR("map batch failed"); + goto out; + } + + if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ) + { + ERROR("get_pfn_type_batch failed"); + goto out; + } + + for ( j = 0; j < batch; j++ ) + { + if ( (pfn_type[j] & LTAB_MASK) == XTAB ) + { + DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]); + continue; + } + + if ( 0 && debug ) + fprintf(stderr, "%d pfn= %08lx mfn= %08lx [mfn]= %08lx" + " sum= %08lx\n", + iter, + (pfn_type[j] & LTAB_MASK) | pfn_batch[j], + pfn_type[j], + live_mfn_to_pfn_table[pfn_type[j]&(~LTAB_MASK)], + csum_page(region_base + (PAGE_SIZE*j))); + + /* canonicalise mfn->pfn */ + pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j]; + } + + if ( (*writerfn)(writerst, &batch, sizeof(int) ) ) + { + ERROR("Error when writing to state file (2)"); + goto out; + } + + if ( (*writerfn)(writerst, pfn_type, sizeof(unsigned long)*j ) ) + { + ERROR("Error when writing to state file (3)"); + goto out; + } + + /* entering this loop, pfn_type is now in pfns (Not mfns) */ + for( j = 0; j < batch; j++ ) + { + /* write out pages in batch */ + if( (pfn_type[j] & LTAB_MASK) == XTAB) + { + DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]); + continue; + } + + if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || + ((pfn_type[j] & LTAB_MASK) == L2TAB) ) + { + memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE); + + for ( k = 0; + k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? + (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : + 1024); + k++ ) + { + unsigned long pfn; + + if ( !(page[k] & _PAGE_PRESENT) ) + continue; + + mfn = page[k] >> PAGE_SHIFT; + pfn = live_mfn_to_pfn_table[mfn]; + + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) ) + { + /* I don't think this should ever happen */ + printf("FNI %d : [%08lx,%d] pte=%08lx, " + "mfn=%08lx, pfn=%08lx [mfn]=%08lx\n", + j, pfn_type[j], k, + page[k], mfn, live_mfn_to_pfn_table[mfn], + (live_mfn_to_pfn_table[mfn]>28, + j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT); +#endif + + } /* end of page table rewrite for loop */ + + if ( (*writerfn)(writerst, page, PAGE_SIZE) ) + { + ERROR("Error when writing to state file (4)"); + goto out; + } + + } /* end of it's a PT page */ + else + { /* normal page */ + + if ( (*writerfn)(writerst, region_base + (PAGE_SIZE*j), + PAGE_SIZE) ) + { + ERROR("Error when writing to state file (5)"); + goto out; + } + } + } /* end of the write out for this batch */ + + sent_this_iter += batch; - verbose_printf("Total pages sent= %d (%.2fx)\n", - total_sent, ((float)total_sent)/nr_pfns ); - verbose_printf("(of which %d were fixups)\n", needed_to_fix ); - } + } /* end of this while loop for this iteration */ - if ( debug && last_iter ) - { - int minusone = -1; - memset( to_send, 0xff, (nr_pfns+8)/8 ); - debug = 0; - printf("Entering debug resend-all mode\n"); - - /* send "-1" to put receiver into debug mode */ - if ( (*writerfn)(writerst, &minusone, sizeof(int)) ) - { - ERROR("Error when writing to state file (6)"); - goto out; - } + munmap(region_base, batch*PAGE_SIZE); - continue; - } + skip: - if ( last_iter ) - break; + total_sent += sent_this_iter; - if ( live ) - { - if ( - // ( sent_this_iter > (sent_last_iter * 0.95) ) || - (iter >= max_iters) || - (sent_this_iter+skip_this_iter < 50) || - (total_sent > nr_pfns*max_factor) ) - { - DPRINTF("Start last iteration\n"); - last_iter = 1; + verbose_printf("\r %d: sent %d, skipped %d, ", + iter, sent_this_iter, skip_this_iter ); - xc_domain_pause( xc_handle, domid ); + if ( last_iter ) + { + print_stats( xc_handle, domid, sent_this_iter, &stats, 1); - } + verbose_printf("Total pages sent= %d (%.2fx)\n", + total_sent, ((float)total_sent)/nr_pfns ); + verbose_printf("(of which %d were fixups)\n", needed_to_fix ); + } - if ( xc_shadow_control( xc_handle, domid, - DOM0_SHADOW_CONTROL_OP_CLEAN2, - to_send, nr_pfns, &stats ) != nr_pfns ) - { - ERROR("Error flushing shadow PT"); - goto out; - } + if ( debug && last_iter ) + { + int minusone = -1; + memset( to_send, 0xff, (nr_pfns+8)/8 ); + debug = 0; + printf("Entering debug resend-all mode\n"); + + /* send "-1" to put receiver into debug mode */ + if ( (*writerfn)(writerst, &minusone, sizeof(int)) ) + { + ERROR("Error when writing to state file (6)"); + goto out; + } + + continue; + } - sent_last_iter = sent_this_iter; + if ( last_iter ) + break; - print_stats( xc_handle, domid, sent_this_iter, &stats, 1); - - } + if ( live ) + { + if ( + /* ( sent_this_iter > (sent_last_iter * 0.95) ) || */ + (iter >= max_iters) || + (sent_this_iter+skip_this_iter < 50) || + (total_sent > nr_pfns*max_factor) ) + { + DPRINTF("Start last iteration\n"); + last_iter = 1; + + xc_domain_pause( xc_handle, domid ); + } + + if ( xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_CLEAN2, + to_send, nr_pfns, &stats ) != nr_pfns ) + { + ERROR("Error flushing shadow PT"); + goto out; + } + + sent_last_iter = sent_this_iter; + + print_stats( xc_handle, domid, sent_this_iter, &stats, 1); + + } } /* end of while 1 */ @@ -839,15 +826,15 @@ int xc_linux_save(int xc_handle, /* Zero terminate */ if ( (*writerfn)(writerst, &rc, sizeof(int)) ) { - ERROR("Error when writing to state file (6)"); - goto out; + ERROR("Error when writing to state file (6)"); + goto out; } /* Get the final execution context */ if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) ) { - PERROR("Could not get full domain info"); - goto out; + PERROR("Could not get full domain info"); + goto out; } /* Canonicalise the suspend-record frame number. */ @@ -873,17 +860,18 @@ int xc_linux_save(int xc_handle, ERROR("PT base is not in range of pseudophys map"); goto out; } - ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT; + ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << + PAGE_SHIFT; - if ( (*writerfn)(writerst, &ctxt, sizeof(ctxt)) || - (*writerfn)(writerst, live_shinfo, PAGE_SIZE) ) + if ( (*writerfn)(writerst, &ctxt, sizeof(ctxt)) || + (*writerfn)(writerst, live_shinfo, PAGE_SIZE) ) { ERROR("Error when writing to state file (1)"); goto out; } munmap(live_shinfo, PAGE_SIZE); -out: + out: if ( pfn_type != NULL ) free(pfn_type); diff --git a/tools/xc/py/Xc.c b/tools/xc/py/Xc.c index adf93c9dd7..f86663c0eb 100644 --- a/tools/xc/py/Xc.c +++ b/tools/xc/py/Xc.c @@ -521,7 +521,7 @@ static PyObject *pyxc_linux_build(PyObject *self, static char *kwd_list[] = { "dom", "control_evtchn", "image", "ramdisk", "cmdline", "flags", - NULL }; + NULL }; if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, &dom, &control_evtchn, -- 2.30.2